﻿/*
 * SharedPtrImpl.h
 *
 *  Created on: 2012/02/26
 *      Author: naoki
 */

#ifndef INCLUDED_NTENGINE_SHAREDPTRIMPL_H
#define INCLUDED_NTENGINE_SHAREDPTRIMPL_H

#include "NTEngine/Base/SharedPtr.h"

namespace NTEngine {

template < typename T > struct SharedPtrTraits {
    typedef T& Reference;
	typedef const T& ConstReference;
};

template<> struct SharedPtrTraits< void > {
    typedef void Reference;
	typedef void ConstReference;
};

template< typename T > void SingleDeleter( T* p ) {
	delete p;
}

template< typename T > void ArraySpDeleter( T* p ) {
	delete[] p;
}

template< class T > SharedPtr< T >::SharedPtr()
: mPtr( 0 )
, mCount() {
}

template< class T > template< class U> SharedPtr< T >::SharedPtr( U* ptr )
: mPtr( static_cast< T* >( ptr ) )
, mCount( ptr, SingleDeleter< U > ) {
}

template< class T > template< class U, class DeleterU > SharedPtr< T >::SharedPtr( U* ptr, DeleterU del )
: mPtr( static_cast< T* >( ptr ) )
, mCount( ptr, del ) {
}

template< class T > template< class U > SharedPtr< T >::SharedPtr( const SharedPtr< U >& a )
: mPtr( static_cast< T* >( a.m_Ptr ) )
, mCount( a.m_Count ) {
}

template< class T > typename SharedPtr< T >::Reference SharedPtr< T >::operator*() {
	ASSERT( mPtr && "null ptr object." );
	return *mPtr;
}

template< class T > typename SharedPtr< T >::ConstReference SharedPtr< T >::operator*() const {
	ASSERT( mPtr && "null ptr object." );
	return *mPtr;
}

template< class T > T* SharedPtr< T >::operator->() {
	ASSERT( mPtr && "null ptr object." );
	return mPtr;
}

template< class T > const T* SharedPtr< T >::operator->() const {
	ASSERT( mPtr && "null ptr object." );
	return mPtr;
}

template< class T > typename SharedPtr< T >::Reference SharedPtr< T >::operator[]( int i ) {
	ASSERT( mPtr && "null ptr object." );
	return mPtr[ i ];
}

template< class T > typename SharedPtr< T >::ConstReference SharedPtr< T >::operator[]( int i ) const {
	ASSERT( mPtr && "null ptr object." );
	return mPtr[ i ];
}

template< class T > bool SharedPtr< T >::operator==( const SharedPtr< T >& a ) const {
	return mPtr == a.mPtr;
}

template< class T > bool SharedPtr< T >::operator!=( const SharedPtr< T >& a ) const {
	return mPtr != a.mPtr;
}

template< class T > bool SharedPtr< T >::operator<( const SharedPtr< T >& a ) const {
	return mPtr < a.mPtr;
}

template< class T > SharedPtr< T >::operator void*() const {
	return ( mPtr ) ? reinterpret_cast< void* >( ~0 ) : 0;
}

//
template< class T > SharedPtr< T > SharedPtrCreator::create( T* p ) {
	return SharedPtr< T >( p );
}

template< class T > SharedPtr< T > SharedPtrCreator::createArray( T* p ) {
	return SharedPtr< T >( p, ArraySpDeleter< T > );
}

} // namespace NTEngine

#endif // INCLUDED_NTENGINE_SHAREDPTRIMPL_H
